package cn.psvmc.cxzapi.service.store;

import cn.psvmc.cxzapi.config.mybatisplus.service.impl.AbstractService;
import cn.psvmc.cxzapi.constant.GlobalConstant;
import cn.psvmc.cxzapi.enums.ResultCode;
import cn.psvmc.cxzapi.exception.ServiceException;
import cn.psvmc.cxzapi.mapper.customer.TCustomerCouponMapper;
import cn.psvmc.cxzapi.mapper.store.TCouponMapper;
import cn.psvmc.cxzapi.mapper.store.TStoreDetailMapper;
import cn.psvmc.cxzapi.mapper.system.TUserMapper;
import cn.psvmc.cxzapi.model.common.SearchEntity;
import cn.psvmc.cxzapi.model.customer.TCustomerCoupon;
import cn.psvmc.cxzapi.model.store.*;
import cn.psvmc.cxzapi.model.system.TUser;
import cn.psvmc.cxzapi.service.alipay.AlipayCreate;
import cn.psvmc.cxzapi.service.system.ServiceUtil;
import cn.psvmc.cxzapi.util.CodeUtil;
import cn.psvmc.cxzapi.util.ToolUtils;
import com.alipay.api.response.AlipayMarketingActivityOrdervoucherCreateResponse;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 优惠券表 服务实现类
 * @Author auto
 * @Date 2024-08-15
 */
@Service
public class TCouponService extends AbstractService<TCouponMapper, TCoupon> {

    @Resource
    private TCouponMapper tCouponMapper;
    @Resource
    private TCouponCustomerService couponCustomerService;
    @Resource
    private HttpServletRequest request;
    @Resource
    private TUserMapper userMapper;
    @Resource
    private TCouponGoodsService couponGoodsService;
    @Resource
    private ServiceUtil serviceUtil;
    @Resource
    private TCustomerCouponMapper customerCouponMapper;
    @Resource
    private TStoreDetailMapper storeDetailMapper;

    /**
    * @Date auto 2024-08-15 新增优惠券表
    * @Param tCoupon 优惠券表
    * @Return int
    */
    @Transactional(rollbackFor = Exception.class)
    public void add(TCoupon tCoupon) {
        checkParam(tCoupon);//校验必传参数
        tCoupon.setCouponCode(CodeUtil.generateCouponCode());
        tCoupon.setUseNum(tCoupon.getNum());
        Integer storeId = serviceUtil.getStoreId();
        tCoupon.setStoreid(storeId);
        if (ToolUtils.isTrueInteger(tCoupon.getStoreid())) {//商家id不为空，发放类型为2商家
            tCoupon.setGrantType(2);
        } else {
            tCoupon.setGrantType(1);
        }
        if (tCoupon.getBelongType().equals(2)) {//支付宝优惠券
            Map<String, Object> extendParams = storeDetailMapper.getService(storeId);
            List<Integer> goodsIds = tCoupon.getGoodsIds();
            if (ToolUtils.isListNotEmpty(goodsIds)) {//限品、特价券必传
                extendParams.putAll(tCouponMapper.getLimitGoods(goodsIds.get(0), 2));
            }
            AlipayMarketingActivityOrdervoucherCreateResponse response = AlipayCreate.addCoupon(tCoupon, extendParams);
            tCoupon.setActivityId(response.getActivityId());
        }
        tCouponMapper.insert(tCoupon);

        saveCouponCustomerAndGoods(tCoupon);//保存优惠券用户和商品
    }

    //校验必传参数
    private void checkParam(TCoupon tCoupon) {
        Integer userScope = tCoupon.getUserScope();
        List<Integer> customerIds = tCoupon.getCustomerIds();
        Integer limitType = tCoupon.getLimitType();
        LocalDateTime begin = tCoupon.getUseTimeBegin();
        LocalDateTime end = tCoupon.getUseTimeEnd();
        if (limitType.equals(1) && !ToolUtils.isTrueInteger(tCoupon.getLimitDay())) {//相对期限
            throw new ServiceException("相对期限天数不能为空！");
        } else if (limitType.equals(2) && (begin == null || end == null)) {//固定期限
            throw new ServiceException("固定期限不能为空！");
        }
        if (userScope.equals(2)) {//指定用户
            if (ToolUtils.isListEmpty(customerIds)) {
                throw new ServiceException("指定用户不能为空！");
            }
        }

        if (tCoupon.getUseScope().equals(2) && ToolUtils.isListEmpty(tCoupon.getGoodsIds())) {
            throw new ServiceException("指定商品不能为空！");
        }
        if (limitType.equals(1)) {
            tCoupon.setUseTimeBegin(null);
            tCoupon.setUseTimeEnd(null);
        }
    }

    //保存优惠券用户和商品
    private void saveCouponCustomerAndGoods(TCoupon tCoupon) {
        Integer limitType = tCoupon.getLimitType();
        Integer limitDay = tCoupon.getLimitDay();
        LocalDateTime useTimeBegin = tCoupon.getUseTimeBegin();
        LocalDateTime useTimeEnd = tCoupon.getUseTimeEnd();
        if (tCoupon.getUserScope().equals(2)) {//指定用户
            Integer couponid = tCoupon.getCouponid();
            List<TCouponCustomer> list = new ArrayList<>();
            TCouponCustomer cc;
            List<TCustomerCoupon> customerCoupons = new ArrayList<>();
            for (Integer customId : tCoupon.getCustomerIds()) {
                cc = new TCouponCustomer();
                cc.setCouponid(couponid);
                cc.setCustomerid(customId);
                list.add(cc);
                TCustomerCoupon customerCoupon = new TCustomerCoupon();
                customerCoupon.setCustomerid(customId);
                customerCoupon.setCouponid(couponid);
                customerCoupon.setCreateid(tCoupon.getCreateid());
                customerCoupon.setCreatetime(LocalDateTime.now());
                LocalDateTime begin;
                LocalDateTime end;
                if (limitType.equals(1)) {//相对期限
                    begin = LocalDateTime.now();
                    end = begin.plusDays(limitDay);
                } else {
                    begin = useTimeBegin;
                    end = useTimeEnd;
                }
                customerCoupon.setBeginDate(begin);
                customerCoupon.setEndDate(end);
                customerCoupons.add(customerCoupon);
            }
            couponCustomerService.saveBatch(list);
            if (ToolUtils.isListNotEmpty(customerCoupons)) {
                customerCouponMapper.insertBatchSomeColumn(customerCoupons);
                String couponids = customerCoupons.stream().map(m -> ToolUtils.objToString(m.getCouponid())).reduce((a, b) -> a + "," + b).orElse("");
                tCouponMapper.updateUseNum(couponids);//更新优惠券可用数量
            }
        }

        if (tCoupon.getUseScope().equals(2)) {//指定商品
            List<TCouponGoods> goodsList = new ArrayList<>();
            TCouponGoods cg;
            for (Integer goodsId : tCoupon.getGoodsIds()) {
                cg = new TCouponGoods();
                cg.setCouponid(tCoupon.getCouponid());
                cg.setGoodsId(goodsId);
                goodsList.add(cg);
            }
            couponGoodsService.saveBatch(goodsList);
        }
    }

    /**
    * @Date auto 2024-08-15 更新优惠券表
    * @Param tCoupon 优惠券表模型
    * @Return int
    */
    @Transactional(rollbackFor = Exception.class)
    public int edit(TCoupon tCoupon) {
        checkObjAndVersion(tCoupon.getCouponid(), tCoupon.getRversion());//校验优惠券和权限
        checkParam(tCoupon);//校验必传参数
        tCouponMapper.deleteCustomerAndGoods(tCoupon.getCouponid());//删除原有用户和商品
        saveCouponCustomerAndGoods(tCoupon);//保存优惠券用户和商品
        // 字段为null 不更新
        return tCouponMapper.updateById(tCoupon);
    }

    //校验优惠券和权限
    private TCoupon checkObjAndVersion(Integer id, Integer rversion) {
        // 通过id查询数据处理 详情
        TCoupon originTCoupon = tCouponMapper.selectById(id);
        if (originTCoupon == null) {
            throw new ServiceException("未查询到对应的优惠券表信息！");
        }

        // 比较数据版本号
        if (!originTCoupon.getRversion().equals(rversion)) {
            throw new ServiceException("数据已更新，请刷新后重试！");
        }

        checkPower(originTCoupon);//校验权限
        return originTCoupon;
    }

    //校验权限
    private void checkPower(TCoupon originTCoupon) {
        int userid = request.getIntHeader(GlobalConstant.USRID);
        TUser tUser = userMapper.selectById(userid);
        Integer grantType = originTCoupon.getGrantType();
        if (tUser == null) {
            throw new ServiceException(ResultCode.NO_USER_ERROR.getMsg());
        } else {
            Integer usertype = tUser.getUsertype();
            if (usertype.equals(1) && grantType.equals(2)) {//平台用户修改商家优惠券
                throw new ServiceException(ResultCode.NO_POWER.getMsg());
            } else if (usertype.equals(2) && !tUser.getStoreid().equals(originTCoupon.getStoreid())) {//商家用户修改其他商家优惠券
                throw new ServiceException(ResultCode.NO_POWER.getMsg());
            }
        }
    }

    /**
    * @Date auto 2024-08-15 查询优惠券表详情
    * @Param id 唯一id
    * @Return cn.psvmc.cxzapi.model.store.TCoupon
    */
    public Map detail(Integer id){
        Map map = tCouponMapper.findByCouponId(id);
        map.put("customerList", couponCustomerService.listByCouponId(id));
        map.put("goodsList", couponGoodsService.listByCouponId(id));
        return map;//根据优惠券ID查询优惠券详情
    }

    /**
    * @Date auto 2024-08-15 删除优惠券表
    * @Param id 唯一id
    * @Param rversion 版本号
    * @Return int
    */
    public void delete(Integer id, Integer rversion) {
        TCoupon coupon = checkObjAndVersion(id, rversion);//校验优惠券和权限

        tCouponMapper.deleteById(id);
        if (coupon.getBelongType().equals(2) && ToolUtils.isNotEmpty(coupon.getActivityId())) {
            AlipayCreate.stoppedCoupon(coupon.getActivityId());
        }
    }

    /**
    * @Date auto 2024-08-15 查询优惠券表列表
    * @Param iPage 分页
    * @Return com.baomidou.mybatisplus.core.metadata.IPage<cn.psvmc.cxzapi.model.store.TCoupon>
    */
    public IPage<Map> list(Page<TCoupon> iPage, SearchEntity entity) {
        serviceUtil.setStoreId(entity);
        return tCouponMapper.listAll(iPage, entity);
    }

    /**
     * @Description 更改优惠券状态
     * @Date 2024/8/20 16:15
     * @Author YWX
     * @Param [id]
     * @Return void
     **/
    public void updateCouponStatus(Integer id, Integer rversion, Integer couponStatus) {
        checkObjAndVersion(id, rversion);
        TCoupon coupon = new TCoupon();
        coupon.setCouponid(id);
        coupon.setCouponStatus(couponStatus);
        tCouponMapper.updateById(coupon);
    }

    /**
     * @Description 修改数量
     * @Date 2024/11/3 9:07
     * @Author YWX
     * @Param [couponid, rversion, num]
     * @Return void
     **/
    public void editNum(Integer couponid, Integer rversion, Integer num) {
        TCoupon originTCoupon = checkObjAndVersion(couponid, rversion);//校验优惠券和权限
        Integer getNum = tCouponMapper.getNumByCouponId(couponid);//根据优惠券ID查询已领取数量
        if (getNum.compareTo(num) > 0) {
            throw new ServiceException("发券数量不能小于已领数量！");
        }
        TCoupon coupon = new TCoupon();
        coupon.setCouponid(couponid);
        coupon.setNum(num);
        coupon.setUseNum(num - getNum);
        tCouponMapper.updateById(coupon);

        Integer belongType = originTCoupon.getBelongType();
        coupon.setBelongType(belongType);
        String activityId = originTCoupon.getActivityId();
        coupon.setActivityId(activityId);
        if (belongType.equals(2) && ToolUtils.isNotEmpty(activityId)) {
            serviceUtil.syncCoupon(activityId);
        }
    }
}
